package JUC.第04章_锁;

import org.junit.Test;

import java.util.concurrent.TimeUnit;

public class C_锁在各种情况的相互影响 {

    @Test
    public void 对象锁等待() {
        LockDemo phone = new LockDemo();
        //A 和 B 用到同一【对象】锁   案例 A抢到锁，B等待，C不需要锁，不等待A
        new Thread(() -> {phone.objLockSleep();}, "A").start();//对象锁
        //睡眠的目的是让  A  先抢到🔒
        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace();}
        new Thread(() -> {phone.objLock();}, "B").start();//对象锁
        new Thread(() -> {phone.noLock();}, "C").start();//无锁

        try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace();}

    }
    @Test
    public void 类锁等待() {
        //A 和 B 用到同一把【类】锁   案例 A抢到锁，B等待，C不需要锁，不等待A
        new Thread(() -> {LockDemo.staticLockSleep();}, "A").start();//对象锁
        //睡眠的目的是让  A  先抢到🔒
        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace();}
        new Thread(() -> {LockDemo.staticLock();}, "B").start();//对象锁
        new Thread(() -> {LockDemo.staticNoLock();}, "C").start();//无锁

        try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace();}
    }

    @Test
    public void 类和对象锁不等待() {
        LockDemo phone = new LockDemo();

        //A 和 B  一个对象锁，一个类锁，根本上不是一把锁，不影响
        new Thread(() -> {phone.objLockSleep();}, "A").start();//对象锁
        //睡眠的目的是让  A  先执行
        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace();}
        new Thread(() -> {LockDemo.staticLock();}, "B").start();//对象锁

        try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace();}
    }

    @Test
    public void 两个对象锁不等待() {
        LockDemo phone1 = new LockDemo();
        LockDemo phone2 = new LockDemo();

        //A 和 B  两个不同的对象  不等待
        new Thread(() -> {phone1.objLockSleep();}, "A").start();//对象锁
        //睡眠的目的是让  A  先执行
        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace();}
        new Thread(() -> {phone2.objLock();}, "B").start();//对象锁

        try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace();}
    }
    @Test
    public void 两个对象一个类锁等待() {
        LockDemo phone1 = new LockDemo();
        LockDemo phone2 = new LockDemo();

        //A 和 B  两个不同的对象 但是 调用的方法是类锁，等待
        new Thread(() -> {phone1.staticLockSleep();}, "A").start();//对象锁
        //睡眠的目的是让  A  先执行
        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace();}
        new Thread(() -> {phone2.staticLock();}, "B").start();//对象锁

        try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace();}
    }
}

/**
 * synchronized 和 static synchronized
 * this            当前类.class
 * 是两把不同的锁
 * 相同锁才有影响
 * 取其根本  就是  synchronized 的锁 就是当前的这个对象
 * static synchronized    锁是当前的class 全局唯一
 *
 */
class LockDemo {
    public synchronized void objLockSleep() {
        try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println("非静态加锁，且睡眠*********************");
    }

    public synchronized void objLock() {
        System.out.println("非静态加锁，不睡眠*********************");
    }//相当于👇
    public void a() { synchronized (this) {}}


    public static synchronized void staticLock() {
        System.out.println("静态加锁，不睡眠*********************");
    }//相当于👇
    public void b() {synchronized (LockDemo.class) {}}

    public static synchronized void staticLockSleep() {
        try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println("静态加锁，睡眠*********************");
    }

    public void noLock(){
        System.out.println("非静态无锁*******************");
    } //没加锁说明他不是内部的方法
    public static void staticNoLock(){
        System.out.println("静态无锁*******************");
    } //没加锁说明他不是内部的方法


}
